/****************************************************************************
**
** MinimapGump.cpp
**
** Copyright (C) August 2014 Hotride
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
*****************************************************************************
*/
//----------------------------------------------------------------------------
#include "stdafx.h"
//----------------------------------------------------------------------------
TMinimapGump::TMinimapGump()
: m_X(0), m_Y(0), m_Minimized(true), m_Count(0), m_Texture(0), m_LastX(0), m_LastY(0)
{
}
//---------------------------------------------------------------------------
void TMinimapGump::GenerateMap()
{
	int m_LastX = UO->GetPlayer()->GetX();
	int m_LastY = UO->GetPlayer()->GetY();

	if (m_Texture != 0) glDeleteTextures(1, &m_Texture);
	m_Texture = 0;

	WORD GumpID = 0x1392;
	if (!m_Minimized) GumpID = 0x1393;

	PTEXTURE_HEADER th = UO->ExecuteGump(GumpID);
	if (th == NULL) return;

	WORD GumpWidth = th->Width;
	WORD GumpHeight = th->Height;

	WORD BlockOffsetX = GumpWidth / 4;
	WORD BlockOffsetY = GumpHeight / 4;

	WORD GumpCenterX = GumpWidth / 2;
	WORD GumpCenterY = GumpHeight / 2;

	PDWORD data = (PDWORD)malloc(GumpWidth * GumpHeight * 4);
	glBindTexture(GL_TEXTURE_2D, th->Texture);
	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
	//0xFF080808 - pixel

	TGameObject *multi_node = UO->m_World->GetMultiNode();

	while (multi_node != NULL)
	{
		TMulti *multi = UO->GetMulti(multi_node->GetGraphic() - 0x4000);

		while (multi != NULL)
		{
			TMultiObject *multiobj = multi->m_Items;

			int X = ((multi_node->GetX() + multi->GetX()) - m_LastX);
			int Y = (multi_node->GetY() + multi->GetY()) - m_LastY;

			int gx = X - Y + GumpCenterX;
			int gy = X + Y + GumpCenterY;

			if (gy >= 0 && gy < GumpHeight)
			{
				while (multiobj != NULL)
				{
					if (multiobj->m_Next == NULL)
					{
						for (int i1 = 0; i1 < 2; i1++)
						{
							gx += i1;

							if (gx < 0 || gx >= GumpWidth) continue;

							int Block = gy * GumpWidth + gx;

							if (data[Block] == 0xFF080808)
							{
								WORD radc = multiobj->GetID() + 0x4000;
								DWORD pcl = UO->m_ColorManager->GetRadarColor(radc);
								data[Block] = (0xFF << 24) | (GetBValue(pcl) << 16) | (GetGValue(pcl) << 8) | GetRValue(pcl);
							}
						}
					}

					multiobj = multiobj->m_Next;
				}
			}

			multi = multi->m_Next;
		}

		multi_node = multi_node->m_MultiNode;
	}

	int MinBlockX = (m_LastX - BlockOffsetX) / 8 - 1;
	int MinBlockY = (m_LastY - BlockOffsetY) / 8 - 1;
	int MaxBlockX = ((m_LastX + BlockOffsetX) / 8) + 1;
	int MaxBlockY = ((m_LastY + BlockOffsetY) / 8) + 1;

	for (int i = MinBlockX; i <= MaxBlockX; i++)
	{
		for (int j = MinBlockY; j <= MaxBlockY; j++)
		{
			MAP_BLOCK mb = {0};
			UO->GetRadarMapBlock(i, j, mb);

			for (int x = 0; x < 8; x++)
			{
				for (int y = 0; y < 8; y++)
				{
					int X = (((i * 8) + x) - m_LastX) + GumpCenterX;
					int Y = ((j * 8) + y) - m_LastY;

					int gx = X - Y;
					int gy = X + Y;

					if (gy < 0 || gy >= GumpHeight) continue;

					for (int i1 = 0; i1 < 2; i1++)
					{
						gx += i1;

						if (gx < 0 || gx >= GumpWidth) continue;

						int Block = gy * GumpWidth + gx;

						if (data[Block] == 0xFF080808)
						{
							DWORD pcl = UO->m_ColorManager->GetRadarColor(mb.Cells[y * 8 + x].TileID);
							data[Block] = (0xFF << 24) | (GetBValue(pcl) << 16) | (GetGValue(pcl) << 8) | GetRValue(pcl);
						}
					}
				}
			}
		}
	}

	UO->m_GL.BindTexture(m_Texture, GumpWidth, GumpHeight, data);

	free(data);
}
//---------------------------------------------------------------------------
void TMinimapGump::GenerateFrame(TGump *gump, float PosX, float PosY)
{
	int PlayerX = UO->GetPlayer()->GetX();
	int PlayerY = UO->GetPlayer()->GetY();

	if (PlayerX != m_LastX || PlayerY != m_LastY) GenerateMap();

	WORD GumpID = 0x1392;
	if (!m_Minimized) GumpID = 0x1393;

	PTEXTURE_HEADER th = UO->ExecuteGump(GumpID);
	if (th == NULL) return;

	WORD GumpWidth = th->Width;
	WORD GumpHeight = th->Height;

	WORD BlockOffsetX = GumpWidth / 4;
	WORD BlockOffsetY = GumpHeight / 4;

	WORD GumpCenterX = GumpWidth / 2;
	WORD GumpCenterY = GumpHeight / 2;

	glNewList((GLuint)gump, GL_COMPILE);

		UO->m_GL.Draw(m_Texture, PosX, PosY, GumpWidth, GumpHeight);
			
		if (m_Count < 6)
		{
			PosX += (GumpCenterX - 1);
			PosY += (GumpCenterY - 1);

			TGameObject *go = UO->m_World->m_Items;
			while (go != NULL)
			{
				if (go->GetContainer() != 0xFFFFFFFF || go->GetGraphic() >= 0x4000)
				{
					go = go->m_Next;
					continue; //Custom multi
				}

				if (go->GetNPC() && go->GetSerial() != UO->GetPlayerSerial())
				{
					int X = go->GetX() - PlayerX;
					int Y = go->GetY() - PlayerY;
					int gx = X - Y;
					int gy = X + Y;
					WORD Color = 0;
					switch ((NOTORIETY_TYPE)go->GetNotoriety())
					{
						case NT_INNOCENT:
						{
							Color = UO->m_ConfigManager.GetInnocentColor();
							break;
						}
						case NT_FRIENDLY:
						{
							Color = UO->m_ConfigManager.GetFriendlyColor();
							break;
						}
						case NT_SOMEONE_GRAY:
						{
							Color = UO->m_ConfigManager.GetSomeoneColor();
							break;
						}
						case NT_CRIMINAL:
						{
							Color = UO->m_ConfigManager.GetCriminalColor();
							break;
						}
						case NT_ENEMY:
						{
							Color = UO->m_ConfigManager.GetEnemyColor();
							break;
						}
						case NT_MURDERER:
						{
							Color = UO->m_ConfigManager.GetMurdererColor();
							break;
						}
						default: break;
					}

					if (Color)
					{
						WORD cell = 5;
						DWORD pcl = UO->m_ColorManager->GetPolygoneColor(cell, Color);
						pcl = (0xFF << 24) | (GetBValue(pcl) << 16) | (GetGValue(pcl) << 8) | GetRValue(pcl);
						
						UO->m_GL.DrawPolygoneSafe(pcl, PosX + gx, PosY + gy, 2, 2);
					}
				}

				go = go->m_Next;
			}

			UO->m_GL.DrawPolygoneSafe(0xFF7F7F7F, PosX, PosY, 2, 2);
		}

	glEndList();
	gump->SetListCreated(true);
}
//----------------------------------------------------------------------------
int TMinimapGump::Draw(bool &mode, TGump *gump)
{
	DWORD Index = (DWORD)gump;

	int PosX = m_X;
	int PosY = m_Y;

	if (g_LeftMouseDown && g_LastGumpLeftMouseDown == Index && !g_LastObjectLeftMouseDown)
	{
		PosX += g_MouseX - g_DroppedLeftMouseX;
		PosY += g_MouseY - g_DroppedLeftMouseY;
		
		if (mode) GenerateFrame(gump, PosX, PosY);
	}
	else if (mode)
	{
		if (!m_Count || m_Count == 6) GenerateFrame(gump, PosX, PosY);
		else if (UO->GetPlayer()->GetX() != m_LastX || UO->GetPlayer()->GetY() != m_LastY) GenerateFrame(gump, PosX, PosY);
	}

	if (mode)
	{
		if (!gump->GetListCreated()) GenerateFrame(gump, PosX, PosY);

		UO->DrawList((GLuint)gump, PosX, PosY);

		m_Count++;
		if (m_Count > 12) m_Count = 0;
	}
	else
	{
		WORD GumpID = 0x1393;
		if (m_Minimized) GumpID = 0x1392;

		if (UO->GumpPixelsInXY(GumpID, PosX, PosY))
		{
			g_LastSelectedObject = 0;
			g_LastSelectedGump = Index;
		}
	}

	return 0;
}
//----------------------------------------------------------------------------